import java.io.IOException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
import org.apache.xmlrpc.server.PropertyHandlerMapping;
import org.apache.xmlrpc.server.XmlRpcServer;
import org.apache.xmlrpc.webserver.WebServer;


public class LaunchServer {
	private JFrameServer jframe;
	private WebServer server;
	private PropertyHandlerMapping phm;
	public static List<ClientInfo> clientList = new ArrayList<ClientInfo>();
	private static SimpleDateFormat formatter = new SimpleDateFormat("hh:mm:ss");
	
	public Integer register(String clientIP, String clientPort){
		Iterator<ClientInfo> ite = clientList.iterator();
		while(ite.hasNext()){
			ClientInfo client = ite.next();
			if(clientIP.equals(client.getIp()) && clientPort.equals(client.getPort())){
				return new Integer(-1);
			}
		}
		synchronized(clientList){
			ClientInfo client = new ClientInfo(clientIP, clientPort,0);
			clientList.add(client);
		}
		System.out.println("client[" + clientIP + ":" + clientPort + "]");
		return new Integer(0);
	}
	
	public Integer disconnect(String clientIP, String clientPort){
		Iterator<ClientInfo> ite = clientList.iterator();
		while(ite.hasNext()){
			ClientInfo client = ite.next();
			if(clientIP.equals(client.getIp()) && clientPort.equals(client.getPort())){
				synchronized(clientList){
					clientList.remove(client);
					System.out.println("JavaServer: " + "remove client[" + clientIP + ":" + clientPort + "]");
				}
				return new Integer(0);
			}
		}
		return new Integer(-1);
	}
	
	
	public Integer updateInterval(String ip, String port, int interval){
		if(interval < 1){
			return new Integer(-1);
		}
		synchronized(clientList){
			Iterator<ClientInfo> ite = clientList.iterator();
			while(ite.hasNext()){
				ClientInfo clientInfo = ite.next();
				if(ip.equals(clientInfo.getIp()) && port.equals(clientInfo.getPort())){
					clientInfo.setInterval(interval - 1);
					return new Integer(0);
				}
			}
		}
		return new Integer(-1);
	}
	
	
	
	public void showFrame(){
		jframe = new JFrameServer();
		jframe.setVisible(true);
		jframe.setCurrentTime(formatter.format(new Date()));
	}

	public void startServer(){
		server = new WebServer(Integer.valueOf(XMLUtil.serverPort).intValue());
		phm = new PropertyHandlerMapping();
	    try {
			phm.addHandler("server", LaunchServer.class);
			XmlRpcServer xmlRpcServer = server.getXmlRpcServer();
		    xmlRpcServer.setHandlerMapping(phm);
		    server.start();
		} catch (XmlRpcException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	     
	}
	

	
	public void notifyClients(){
		synchronized(clientList){
			for(int i = 0; i < clientList.size(); i++){
				ClientInfo clientInfo = clientList.get(i);
				try{
					if(clientInfo.getGoneTime() == clientInfo.getInterval()){
						XmlRpcClientConfigImpl config;
						XmlRpcClient client;
					    config = new XmlRpcClientConfigImpl();
					    config.setServerURL(new URL("http://" + clientInfo.getIp() + ":" + clientInfo.getPort()));
					    client = new XmlRpcClient(); 
					    client.setConfig(config);
					    Vector<String> params = new Vector<String>();
					    params.addElement(formatter.format(new Date())); 
					    client.execute("sample.timeAccept", params);
					    clientInfo.setGoneTime(0);
					}else{
						clientInfo.increaseGoneTime();
					}
					}catch(Exception exception){
						System.err.println("JavaServer: " + exception);
						System.err.println("JavaServer: " + "remove client[" + clientInfo.getIp() + ":" + clientInfo.getPort() + "]");
						clientList.remove(clientInfo);
						i--;
					}
			}
			jframe.setCurrentTime(formatter.format(new Date()));
		}
	}

	public static void main(String[] args){
		XMLUtil.fetchXML();
		final LaunchServer launchServer = new LaunchServer();
		launchServer.startServer();
		launchServer.showFrame();
		Timer timer = new Timer();
	    TimerTask tt=new TimerTask(){public void run(){launchServer.notifyClients();}};
	    timer.schedule(tt, new Date(),1000);
	    System.out.println("server is working....");
	}
}
